package com.ltx.mysqlcanalestest.service;

import com.ltx.mysqlcanalestest.domain.es.Hotel;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.UpdateQuery;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component
public class HotelDocumentOperator {

    @Resource
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    // 新增文档
    public void saveDocument(Hotel hotel) {
        elasticsearchRestTemplate.save(hotel);
    }

    // 根据ID查询文档
    public Hotel getDocumentById(String id) {
        return elasticsearchRestTemplate.get(id, Hotel.class);
    }

    // 复杂查询（示例：按酒店名称模糊查询）
    public List<Hotel> searchDocumentsByName(String name) {
        // 构建查询条件，这里使用 match 查询实现酒店名称模糊搜索
        QueryBuilder queryBuilder = QueryBuilders.matchQuery("hotelName", name);
        NativeSearchQuery searchQuery = new NativeSearchQuery(queryBuilder);
        return elasticsearchRestTemplate.search(searchQuery, Hotel.class).getSearchHits().stream().map(hit -> hit.getContent()).collect(Collectors.toList());
    }

    public List<Hotel> searchDocumentsTermByName(String brand) {
        // 构建查询条件，这里使用 match 查询实现酒店名称模糊搜索
        QueryBuilder queryBuilder = QueryBuilders.termQuery("brand", brand);
        NativeSearchQuery searchQuery = new NativeSearchQuery(queryBuilder);
        return elasticsearchRestTemplate.search(searchQuery, Hotel.class).getSearchHits().stream().map(hit -> hit.getContent()).collect(Collectors.toList());
    }

    public List<Hotel> searchDocumentsByRatingRange(double minRating, double maxRating) {
        // 构建查询条件，这里使用 range 查询实现酒店评分范围搜索
        QueryBuilder queryBuilder = QueryBuilders.rangeQuery("rating").gte(minRating).lte(maxRating);
        NativeSearchQuery searchQuery = new NativeSearchQuery(queryBuilder);
        return elasticsearchRestTemplate.search(searchQuery, Hotel.class).getSearchHits().stream().map(hit -> hit.getContent()).collect(Collectors.toList());
    }

    public List<Hotel> searchDocumentsByBrandAndRatingRange(String brand, double minRating, double maxRating) {
        // 构建查询条件，这里使用 bool 查询实现品牌和评分范围搜索
        QueryBuilder queryBuilder = QueryBuilders.boolQuery()
                .must(QueryBuilders.termQuery("hotelBrand", brand))
                .should(QueryBuilders.rangeQuery("rating").gte(minRating).lte(maxRating));
        NativeSearchQuery searchQuery = new NativeSearchQuery(queryBuilder);
        return elasticsearchRestTemplate.search(searchQuery, Hotel.class).getSearchHits().stream().map(hit -> hit.getContent()).collect(Collectors.toList());
    }



    // 更新文档（部分更新）
    public void updateDocumentPartially(String id, Map<String, Object> fieldsToUpdate) {
        if (elasticsearchRestTemplate.exists(id, Hotel.class)) {
            org.springframework.data.elasticsearch.core.document.Document document = org.springframework.data.elasticsearch.core.document.Document.from(fieldsToUpdate);
            UpdateQuery updateQuery = UpdateQuery.builder(id)
                    .withDocument(document)
                    .build();
            elasticsearchRestTemplate.update(updateQuery, org.springframework.data.elasticsearch.core.mapping.IndexCoordinates.of("hotel_index"));
        } else {
            throw new IllegalArgumentException("Document with ID " + id + " does not exist");
        }
    }

    public List<Hotel> searchDocumentsByBrandAndRatingRange(String brand, double minRating, double maxRating, int page, int size, String sortBy, boolean ascending) {
        // 构建查询条件，这里使用 bool 查询实现品牌和评分范围搜索
        QueryBuilder queryBuilder = QueryBuilders.boolQuery()
                .must(QueryBuilders.termQuery("hotelBrand", brand))
                .should(QueryBuilders.rangeQuery("rating").gte(minRating).lte(maxRating));

        // 构建分页和排序参数
        Sort sort = Sort.by(new Sort.Order(ascending ? Sort.Direction.ASC : Sort.Direction.DESC, sortBy).ignoreCase());
        PageRequest pageRequest = PageRequest.of(page, size, sort);

        NativeSearchQuery searchQuery = new NativeSearchQuery(queryBuilder);
        searchQuery.setPageable(pageRequest);

        return elasticsearchRestTemplate.search(searchQuery, Hotel.class).getSearchHits().stream().map(hit -> hit.getContent()).collect(Collectors.toList());
    }

    // 删除文档
    public void deleteDocument(String id) {
        elasticsearchRestTemplate.delete(id,Hotel.class);
    }

    // 批量新增文档
    public void saveDocuments(List<Hotel> hotelList) {
        hotelList.forEach(elasticsearchRestTemplate::save);
    }

    // 批量删除文档
    public void deleteDocuments(List<String> ids) {
        ids.forEach(elasticsearchRestTemplate::delete);
    }

}